package org.moonlight.jvm.natives;

import org.moonlight.jvm.rtda.exclusive.Frame;

import java.util.HashMap;
import java.util.Map;

/**
 * 本地方法接口
 *
 * @author Moonlight
 * @createTime 2023/9/20 14:05
 **/
public interface NativeMethod {

    /** java object 类全限定名 **/
    String JAVA_LANG_OBJECT = "java/lang/Object";
    /** java class 类全限定名 **/
    String JAVA_LANG_CLASS = "java/lang/Class";

    /**
     * 本地方法
     *
     * @param frame 本地方法栈
     * @createTime 14:06 2023/9/20
     * @author moonlight
     **/
    void nativeMethod(Frame frame);

    /** 本地方法注册表 **/
    Map<String, NativeMethod> REGISTRY = new HashMap<>();

    /** 空实现 **/
    NativeMethod EMPTY_NATIVE_METHOD = new EmptyNativeMethod();

    /**
     * 将本地方法注册到 本地方法注册表中去
     *
     * @param className 方法所在类的类名
     * @param methodName 方法名
     * @param methodDescriptor 方法描述符
     * @createTime 14:32 2023/9/20
     * @author moonlight
     **/
    default void registry(String className, String methodName, String methodDescriptor) {
        String key = className + "_" + methodName + "_" + methodDescriptor;
        REGISTRY.put(key, this);
    }

    /**
     * 根据 方法所在类的类名，方法名，方法描述符 从 本地方法注册表 中查找 本地方法
     *
     * @param className 方法所在类的类名
     * @param methodName 方法名
     * @param methodDescriptor 方法描述符
     * @return NativeMethod
     * @createTime 14:42 2023/9/20
     * @author moonlight
     **/
    static NativeMethod findNativeMethod(String className, String methodName, String methodDescriptor) {
        String key = className + "_" + methodName + "_" + methodDescriptor;
        if (REGISTRY.containsKey(key)) {
            return REGISTRY.get(key);
        }
        // java.lang.Object等类是通过一个叫作registerNatives()的本地方法来注册其他本地方法的
        if ("()V".equals(methodDescriptor) && "registerNatives".equals(methodName)) {
            return EMPTY_NATIVE_METHOD;
        }
        return null;
    }

}